package org.concordia.wsdl.main;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

import org.concordia.wsdl.evaluator.BFStarEvaluator;
import org.concordia.wsdl.evaluator.Evaluator;
import org.concordia.wsdl.evaluator.LookaheadBFStarEvaluator;
import org.concordia.wsdl.evaluator.RevisedLookaheadBFStarEvaluator;
import org.concordia.wsdl.filter.BloomFilter;
import org.concordia.wsdl.filter.Filter;
import org.concordia.wsdl.filter.TranditionalFilter;
import org.concordia.wsdl.helper.CompositionUtils;
import org.concordia.wsdl.helper.ListUtils;
import org.concordia.wsdl.helper.ProblemWrapper;
import org.concordia.wsdl.helper.WebServiceWrapper;
import org.concordia.wsdl.model.Problem;
import org.concordia.wsdl.model.WebService;

public class BFStarMain {

	private static final String WS_REPO = "/org/concordia/wsdl/dataset";
	private static URL ws_url = TraditionalMain.class.getResource(WS_REPO);

	private static final String TASK = "/org/concordia/wsdl/problemset/EEE05Challenge.xml";
	private static URL task_url = TraditionalMain.class.getResource(TASK);

	private static List<WebService> webServices;
	private static List<Problem> problems;

	private static List<WebService> invokedServices;
	private static List<WebService> remainingServices;
	private static List<String> knownParams;
	private static List<String> rOut;

	
	private static BloomFilter<String> filter = new BloomFilter<String>(100, 10);
	private static Boolean BF = true;

	//private static Evaluator evaluator = new BFStarEvaluator();
	//private static Evaluator evaluator = new LookaheadBFStarEvaluator();
	private static Evaluator evaluator = new RevisedLookaheadBFStarEvaluator();


	/**
	 * @param args
	 */
	public static void main(String[] args) {

		/**
		 * parsing XML files
		 */
		try
		{
			initialize();

			long startMil	=	System.currentTimeMillis();
			long currentMil;

			for (Problem p : problems) {
				filter.clear();
				currentMil = System.currentTimeMillis();
				solve(p);
				System.out.println("COMPOSITION TIME/MILLISECOND  : " + (System.currentTimeMillis() - currentMil) + "ms");
				System.out.println("<" + filter.getName() + " APPLIED>");

			}

			System.out.println("\nTOTAL COMPOSITION TIME/MILLISECOND : " + (System.currentTimeMillis() - startMil) + "ms");
		}
		catch(Exception e)
		{
			System.out.println(e.getMessage());
		}
	}

	private static void initialize() {
		try {
			WebServiceWrapper wsWrapper = new WebServiceWrapper();
			ProblemWrapper cpWrapper = new ProblemWrapper();

			//wsWrapper.doParse("/Users/ericzhao/Desktop/1300expo");
			wsWrapper.doParse(ws_url.getPath());
			webServices = wsWrapper.services;

			//cpWrapper.doParse("/Users/ericzhao/Desktop/goal4.xml");
			cpWrapper.doParse(task_url.getPath());
			problems = cpWrapper.problems;

		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	private static void solve(Problem p) throws Exception{

		int level = 0;

		remainingServices = ListUtils.copyListWS(webServices);
		invokedServices = new LinkedList<WebService>();
		knownParams = ListUtils.copyList(p.getInputs());
		rOut = ListUtils.copyList(p.getOutputs());


		WebService current = new WebService();
		current.setName("R");
		for (String s : p.getInputs()) {
			current.addOutput(s);
		}

		System.out.println("\n\n");
		System.out.println("Problem: " + p.getName());
		System.out.println("************************");
		System.out.println("*** BEGIN COMPOSITION***");
		System.out.println("************************");

		
		filter.addAll(knownParams);
		while (!filter.containsAll(rOut)) {

			//System.out.println("***Known Params:");
			//printParams(knownParams);

			List<WebService> candidates = CompositionUtils.getCandidates(
					remainingServices, current, knownParams);
			for (WebService candidate : candidates) {
				evaluator.evaluate(candidate, rOut, knownParams,
						invokedServices, remainingServices, candidates);
			}
			current = CompositionUtils.getBestWS(candidates);
			if (current == null) {
				System.out.println("*****************");
				System.out.println("*** NOT Found!***");
				System.out.println("*****************");

//				System.out.println("***Invorked WS:");
//				for(WebService ws : invokedServices){
//					System.out.println("==" + ws.getName());
//				}


				break;
			}
			remainingServices.remove(current);
			invokedServices.add(current);
			knownParams = ListUtils.union(knownParams, current.getOutputs());
			filter.addAll(current.getOutputs());


//			System.out.println("***Current input Params:");
//			printParams(current.getInputs());

			printPath(current);
			level++;
		}
		if (filter.containsAll(rOut)) {
			System.out.println("***********************");
			System.out.println("***Goal State Found!***");
			System.out.println("***********************");
			System.out.println("COMPOSITION LEVEL: " + level);

		}

	}

	private static void printPath(WebService ws) {
		System.out.println("invoke service: " + ws.getName() + " ("
				+ ws.getScore() + ")" + " =>");
	}

	private static void printParams(List<String> params) {
		for (String p : params) {
			System.out.println(p);
		}
	}

}
